#include "dht11.h"
#include "delay.h"

static void DHT11_IO_OUT(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
}

static void DHT11_IO_IN(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure);
}

void DHT11_Init(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    DHT11_IO_OUT();
    GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);
}

static uint8_t DHT11_Read_Byte(void) {
    uint8_t i, data = 0;
    
    for(i=0; i<8; i++) {
        while(GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET);
        delay_us(40);
        
        if(GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)) {
            data |= (1 << (7-i));
            while(GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN));
        }
    }
    return data;
}

uint8_t DHT11_Read_Data(int16_t *temp, int16_t *humi) {
    uint8_t buf[5];
    uint8_t i;
    
    DHT11_IO_OUT();
    GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);
    delay_ms(18);
    GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN);
    delay_us(30);
    
    DHT11_IO_IN();
    if(GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)) return 0;
    delay_us(80);
    if(!GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN)) return 0;
    delay_us(80);
    
    for(i=0; i<5; i++) {
        buf[i] = DHT11_Read_Byte();
    }
    
    if(buf[4] == (buf[0] + buf[1] + buf[2] + buf[3])) {
        *humi = buf[0];
        *temp = buf[2];
        return 1;
    }
    return 0;
}